package com.wsoft.hr.pm.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.wsoft.bpm.constants.BpmConstant;
import com.wsoft.bpm.controller.BpmDefController;
import com.wsoft.bpm.dto.ActModelDTO;
import com.wsoft.bpm.dto.ActModelDataDTO;
import com.wsoft.bpm.enums.BranchType;
import com.wsoft.bpm.enums.ExecuteCategory;
import com.wsoft.bpm.enums.ListenerEvent;
import com.wsoft.bpm.enums.ListenerType;
import com.wsoft.bpm.query.node.*;
import com.wsoft.bpm.service.IActReModelService;
import com.wsoft.bpm.service.IActWorkflowConfigService;
import com.wsoft.bpm.utils.ActivityUtils;
import com.wsoft.hr.pm.enums.HrProcessFlowStageEnum;
import com.wsoft.hr.pm.query.process.activity.HrPmProcessActivityQuery;
import com.wsoft.hr.pm.query.process.activity.HrPmProcessActivitySaveQuery;
import com.wsoft.hr.pm.query.process.activity.HrProcessActivityCardQuery;
import com.wsoft.hr.pm.service.IHrPmProcessActivityService;
import com.wsoft.hr.pm.vo.process.activity.HrPmProcessActivityDataVO;
import com.wsoft.response.ResponseResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;

/**
 * 活动考核流程主表 前端控制器
 *
 * @author zhonglj
 * @since 2025年02月28日 18:19:01
 */
@RestController
@Tag(name = "考评活动-考核流程")
@RequestMapping("/hr/pm/process/activity")
public class HrPmProcessActivityController {
    @Resource
    private IHrPmProcessActivityService activityService;

    @Operation(summary = "获取考评活动考核流程数据", description = "根据考评活动id获取模版考核流程数据")
    @GetMapping("/getByMemberTemplateId")
    public ResponseResult<HrPmProcessActivityDataVO> getByMemberTemplateId(@RequestParam("memberTemplateId") Long memberTemplateId) {
        return ResponseResult.success(activityService.getByMemberTemplateId(memberTemplateId));
    }

    @Operation(summary = "暂时保存考评活动考核流程", description = "暂时保存考评活动考核流程")
    @PostMapping("/tempSave")
    public ResponseResult tempSave(@RequestBody HrPmProcessActivitySaveQuery saveQuery) {
        // 1. 排序流程阶段
        saveQuery.getFlowStages().sort(Comparator.comparingInt(HrPmProcessActivityQuery::getSort));
        // 2. 对每个流程阶段的卡片排序
        saveQuery.getFlowStages().forEach(flowStage -> {
            flowStage.getCards().sort(
                    Comparator.comparingInt(HrProcessActivityCardQuery::getSerialSort)
                            .thenComparingInt(HrProcessActivityCardQuery::getParallelSort)
            );
        });

        // 设置默认的工作流程
        setDefaultProcessDefKey(saveQuery);
        activityService.saveProcess(saveQuery);
        return ResponseResult.success("[sys.msg.success]");
    }


    @Operation(summary = "保存考评活动考核流程", description = "保存考评活动考核流程")
    @PostMapping("/save")
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult save(@RequestBody @Validated HrPmProcessActivitySaveQuery saveQuery) {
        // 1. 排序流程阶段
        saveQuery.getFlowStages().sort(Comparator.comparingInt(HrPmProcessActivityQuery::getSort));
        // 2. 对每个流程阶段的卡片排序
        saveQuery.getFlowStages().forEach(flowStage -> {
            flowStage.getCards().sort(
                    Comparator.comparingInt(HrProcessActivityCardQuery::getSerialSort)
                            .thenComparingInt(HrProcessActivityCardQuery::getParallelSort)
            );
        });

        // 设置默认的工作流程
        setDefaultProcessDefKey(saveQuery);
        activityService.saveProcess(saveQuery);
        // 更新工作流审批链
        for (HrProcessFlowStageEnum stageEnum : HrProcessFlowStageEnum.values()) {
            activityService.resetWorkFlowChain(saveQuery.getMemberTemplateId(), stageEnum);
        }
        return ResponseResult.success("[sys.msg.success]");
    }

    private void setDefaultProcessDefKey(HrPmProcessActivitySaveQuery saveQuery) {
        if (saveQuery != null) {
            List<HrPmProcessActivityQuery> flowStages = saveQuery.getFlowStages();
            if (CollUtil.isNotEmpty(flowStages)) {
                for (HrPmProcessActivityQuery flowStage : flowStages) {
                    HrProcessFlowStageEnum stageEnum = HrProcessFlowStageEnum.getEnum(flowStage.getFlowStage());
                    if (stageEnum != null) {
                        flowStage.setProcDefKey(stageEnum.getProcessDefKey());
                    }
                }
            }
        }
    }

    @Operation(summary = "测试复制模版考评流程", description = "测试复制模版考评流程")
    @GetMapping("/testCopy")
    public ResponseResult testCopy(@RequestParam Long templateId, @RequestParam Long memberTemplateId) {
        return ResponseResult.success(activityService.copyTemplate(templateId, memberTemplateId));
    }

    @Operation(summary = "测试获取审批链", description = "测试获取审批链")
    @GetMapping("/getApprovalChainNodes")
    public ResponseResult getApprovalChainNodes(@RequestParam Long memberTemplateId) {
        return ResponseResult.success(activityService.getApprovalChainNodes(memberTemplateId, HrProcessFlowStageEnum.CHECK_TARGET));
    }

    @Operation(summary = "测试获取当前动态审批链节点", description = "测试获取当前动态审批链节点")
    @GetMapping("/getProcessActivityNode")
    public ResponseResult getProcessActivityNode(@RequestParam String businessKey) {
        return ResponseResult.success(activityService.getProcessActivityNode(businessKey));
    }


    @Resource
    private IActReModelService actReModelService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private BpmDefController bpmDefController;
    @Resource
    private IActWorkflowConfigService actWorkflowConfigService;

    @Operation(summary = "测试流程创建", description = "测试流程创建")
    @GetMapping("/testInitModel")
    public ResponseResult testInitModel() throws Exception {
        for (HrProcessFlowStageEnum stage : HrProcessFlowStageEnum.values()) {
            Model model = repositoryService.createModelQuery().modelKey(stage.getProcessDefKey()).singleResult();
            String modelId = null;
            // 流程模型
            if (model == null) {
                ActModelDTO modelDTO = new ActModelDTO();
                modelDTO.setDesc(stage.getDesc());
                modelDTO.setCategory("绩效系统");
                modelDTO.setKey(stage.getProcessDefKey());
                modelDTO.setName("绩效系统-" + stage.getDesc());
                modelId = actReModelService.createModel(modelDTO);
            } else {
                modelId = model.getId();
            }

            // 流程设计
            String dataXml = createHrProcDefData(stage.getProcessDefKey(), modelId);
            ActModelDataDTO modelDataDTO = new ActModelDataDTO();
            modelDataDTO.setModelId(modelId);
            modelDataDTO.setData(dataXml);
            actReModelService.saveModelData(modelDataDTO);

            // 流程部署
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(stage.getProcessDefKey())
                    .latestVersion()
                    .singleResult();

            actReModelService.deploy(modelId);

        }

        return ResponseResult.success("[sys.msg.success]");
    }

    private String createHrProcDefData(String procDefKey, String modelId) throws Exception {
        String startEventId = BpmConstant.GENERATE_ID_PREFIX_START_EVENT + IdUtil.fastSimpleUUID();
        String userTaskId = BpmConstant.GENERATE_ID_PREFIX_USERTASK + IdUtil.fastSimpleUUID();
        String endEventId = BpmConstant.GENERATE_ID_PREFIX_END_EVENT + IdUtil.fastSimpleUUID();
        String flow1 = BpmConstant.GENERATE_ID_PREFIX_SEQUENCE_FLOW + IdUtil.fastSimpleUUID();
        String flow2 = BpmConstant.GENERATE_ID_PREFIX_SEQUENCE_FLOW + IdUtil.fastSimpleUUID();
        String data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<definitions " +
                "xmlns:bpmn=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" " +
                "xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" " +
                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
                "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
                "xmlns:activiti=\"http://activiti.org/bpmn\" " +
                "xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" " +
                "xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" " +
                "xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" " +
                "typeLanguage=\"http://www.w3.org/2001/XMLSchema\" " +
                "expressionLanguage=\"http://www.w3.org/1999/XPath\" " +
                "targetNamespace=\"http://www.activiti.org/test\">\n" +
//                "  <bpmn:process id=\"" + procDefKey + "\" name=\"" + procDefKey + "\" isExecutable=\"true\">\n" +
                bpmDefController.process(new ProcessQuery()
                        .setModelId(modelId)
                        .setId(procDefKey)
                        .setName(procDefKey)
                ).getData().replace("</bpmn:process>", "") + "\n" +
//                "<bpmn:startEvent id=\"StartEvent211eea3755df49639a2409c7e4378e5a\" name=\"开始\" activiti:initiator=\"\" />\n" +
                bpmDefController.startEvent(new StartEventQuery()
                        .setModelId(modelId)
                        .setId(startEventId)
                        .setName("开始")
                ).getData() + "\n" +
//                "        <bpmn:userTask id=\"UserTaskead5d78599ac483b893bf1f2a449df60\" name=\"动态审批\" activiti:formKey=\"\" activiti:assignee=\"system\" activiti:priority=\"50\" activiti:skipExpression=\"\">\n" +
//                "            <bpmn:documentation>审批</bpmn:documentation>\n" +
//                "            <bpmn:extensionElements>\n" +
//                "                <activiti:taskListener expression=\"${expressionListenerBean.createDynamicApprovalChain(task,&#39;kamui&#39;)}\" event=\"create\" />\n" +
//                "            </bpmn:extensionElements>\n" +
//                "        </bpmn:userTask>\n" +
                bpmDefController.task(new TaskQuery()
                        .setModelId(modelId)
                        .setId(userTaskId)
                        .setName("动态审批")
                        .setBranchType(BranchType.AUTO.getValue())
                        .setPriority("50")
                        .setExecuteCategory(ExecuteCategory.EXECUTE.getValue())
                        .setTaskExecute(new TaskExecuteQuery().setExpression("system"))
                        .setListeners(actWorkflowConfigService.addListener(
                                null,
                                ListenerEvent.TASK_CREATE.getValue(),
                                ListenerType.EXPRESSION.getValue(),
                                "${expressionListenerBean.createDynamicApprovalChain(task,'approveChain')}",
                                "初始化动态审批"))
                ).getData() + "\n" +
//                "        <bpmn:sequenceFlow id=\"Flow_124j939\" sourceRef=\"StartEvent211eea3755df49639a2409c7e4378e5a\" targetRef=\"UserTaskead5d78599ac483b893bf1f2a449df60\" />\n" +
                bpmDefController.sequenceFlow(new SequenceFlowQuery()
                        .setModelId(modelId)
                        .setId(flow1)
                        .setSourceRef(startEventId)
                        .setTargetRef(userTaskId)
                ).getData() + "\n" +
//                "        <bpmn:sequenceFlow id=\"Flow_048x3xu\" sourceRef=\"UserTaskead5d78599ac483b893bf1f2a449df60\" targetRef=\"EndEvent2e35dcc7340a4076ac891a4a64408c3d\" />\n" +
                bpmDefController.sequenceFlow(new SequenceFlowQuery()
                        .setModelId(modelId)
                        .setId(flow2)
                        .setSourceRef(userTaskId)
                        .setTargetRef(endEventId)
                ).getData() + "\n" +
//                "        <bpmn:endEvent id=\"EndEvent2e35dcc7340a4076ac891a4a64408c3d\" name=\"结束\">\n" +
//                "            <bpmn:extensionElements>\n" +
//                "                <activiti:executionListener delegateExpression=\"${processEndCallBackListener}\" event=\"end\" />\n" +
//                "            </bpmn:extensionElements>\n" +
//                "            <bpmn:incoming>Flow_048x3xu</bpmn:incoming>\n" +
//                "        </bpmn:endEvent>" +
                bpmDefController.endEvent(new EndEventQuery()
                        .setModelId(modelId)
                        .setId(endEventId)
                        .setName("结束")
                        .setListeners(actWorkflowConfigService.addListener(
                                null,
                                ListenerEvent.EXECUTION_END.getValue(),
                                ListenerType.DELEGATE_EXPRESSION.getValue(),
                                "${processEndCallBackListener}",
                                "流程正常结束监听器"))
                ).getData() + "\n" +
                "  </bpmn:process>\n" +

                "<bpmndi:BPMNDiagram id=\"BPMNDiagram_1\">\n" +
                "        <bpmndi:BPMNPlane id=\"BPMNPlane_1\" bpmnElement=\"" + procDefKey + "\">\n" +
                "            <bpmndi:BPMNShape id=\"_BPMNShape_" + startEventId + "\" bpmnElement=\"" + startEventId + "\">\n" +
                "                <omgdc:Bounds x=\"2\" y=\"132\" width=\"36\" height=\"36\" />\n" +
                "                <bpmndi:BPMNLabel>\n" +
                "                    <omgdc:Bounds x=\"9\" y=\"175\" width=\"23\" height=\"14\" />\n" +
                "                </bpmndi:BPMNLabel>\n" +
                "            </bpmndi:BPMNShape>\n" +
                "            <bpmndi:BPMNShape id=\"" + userTaskId + "_di\" bpmnElement=\"" + userTaskId + "\">\n" +
                "                <omgdc:Bounds x=\"100\" y=\"125\" width=\"100\" height=\"50\" />\n" +
                "                <bpmndi:BPMNLabel />\n" +
                "            </bpmndi:BPMNShape>\n" +
                "            <bpmndi:BPMNShape id=\"" + endEventId + "_di\" bpmnElement=\"" + endEventId + "\">\n" +
                "                <omgdc:Bounds x=\"252\" y=\"132\" width=\"36\" height=\"36\" />\n" +
                "                <bpmndi:BPMNLabel>\n" +
                "                    <omgdc:Bounds x=\"260\" y=\"175\" width=\"23\" height=\"14\" />\n" +
                "                </bpmndi:BPMNLabel>\n" +
                "            </bpmndi:BPMNShape>\n" +
                "            <bpmndi:BPMNEdge id=\"" + flow1 + "_di\" bpmnElement=\"" + flow1 + "\">\n" +
                "                <omgdi:waypoint x=\"38\" y=\"150\" />\n" +
                "                <omgdi:waypoint x=\"100\" y=\"150\" />\n" +
                "            </bpmndi:BPMNEdge>\n" +
                "            <bpmndi:BPMNEdge id=\"" + flow2 + "_di\" bpmnElement=\"" + flow2 + "\">\n" +
                "                <omgdi:waypoint x=\"200\" y=\"150\" />\n" +
                "                <omgdi:waypoint x=\"252\" y=\"150\" />\n" +
                "            </bpmndi:BPMNEdge>\n" +
                "        </bpmndi:BPMNPlane>\n" +
                "    </bpmndi:BPMNDiagram>" +

                "</definitions>";
        String formatXml = ActivityUtils.formatXml(data);
        return formatXml;
    }
}
